/*

    file:   overlay.h
    desc:   OVERLAY util header.

    note:   The overlay tool uses RAM block capability of the driver to show floating images, primitives, etc.
            overlay_draw(x, y, ...) function behaves just like a putimage(x, y, ...)  
            in a full-graphics environment.

    author: Jaromir Dvorak (md@unicode.cz)

    This file is part of the AVGA platform.
    http://avga.prometheus4.com/
    

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
  
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
*/



#ifndef _OVERLAY_H_
#define _OVERLAY_H_

#include "../config_utils.h"



/* ########## BEGIN OF USER CONFIGURABLE SECTION ########## */
#ifndef OVERLAY_UTILCONFIG
#define OVERLAY_UTILCONFIG

//
// define maximum block count for overlay graphics here.
// the system assumes that appropriate amount of allocated memory was given to driver_mmap(...)
//
#define OVERLAY_BLOCK_COUNT		DRIVER_RAM_BLOCK_COUNT	//use all available blocks

//
// Define this if you want the OVERLAY system to be able to remove drawn objects.
//
#define OVERLAY_CLEARABLE

//
// Select drawing area for overlay. If defined, objects will be drawn into selected window. Otherwise, whole screen is used.
//
#define OVERLAY_WINDOW 

//
// If this is defined, and there's not enough RAM to finish a drawing, eariler allocated blocks will be released.
//
//#define OVERLAY_INVERSE_PRIORITY

//
// Background color for overlay. If defined, the value is used as color to fill the RAM blocks with.
//
//#define OVERLAY_BGCOLOR		4

//
// define if you want to compile functions for simple graphics primitives
//
//#define OVERLAY_PRIMITIVES

//
// define if using overlay_draw.
//
#define OVERLAY_DRAW



//
// The image will be cut if it exceeds drawing area boundaries.
//
//#define OVERLAY_DRAW_SAFE


//
// Theese constans are used only when OVERLAY_DRAW_SAFE is enabled
// They define restricted margins of selected drawing area.
// If leftmargin and topmargin are nonzero, the given x, y coordinates are treated 
// relative to point at x=leftmargin, y=topmargin.
// If any of theese values is zero, operation regarding it is removed by the optimizer. 
// So no unnecesary waste of clock cycles.
//

#define OVERLAY_DRAW_LEFTMARGIN		0
#define OVERLAY_DRAW_RIGHTMARGIN	0
#define OVERLAY_DRAW_TOPMARGIN		0
#define OVERLAY_DRAW_BOTTOMMARGIN	0


//
// EOR all valid pixels of the image with lower 4 bits of param.
//
//#define OVERLAY_DRAW_COLORMODIFY

//
// Allow the image transformations.
//
#define OVERLAY_DRAW_TRANSFORMATIONS

//
// transparent color for overlay_draw, pixels in the drawn image with this color will not change underlay pixels.
// If not defined, all source image pixels will be visible.
//
#define OVERLAY_DRAW_ALPHA		0


#endif
/* ########### END OF USER CONFIGURABLE SECTION ########### */





/*
 * 
 * Defined options combination.
 *
 */

#if defined(OVERLAY_CLEARABLE) || defined(OVERLAY_INVERSE_PRIORITY)
#define OVERLAY_REMEMBER_BLOCKS
#endif

#if defined(OVERLAY_DRAW_COLORMODIFY) || defined(OVERLAY_DRAW_TRANSFORMATIONS)
#define OVERLAY_DRAW_PARAM
#endif

#if defined(OVERLAY_DRAW_SAFE) || defined(OVERLAY_DRAW_TRANSFORMATIONS)
#define OVERLAY_DRAW_IMGADDR
#endif


/*
 * 
 * Param values for image transformations in overlay_draw. You can combine them with OR.
 *
 */

#define OVERLAY_HFLIP			0x10
#define OVERLAY_VFLIP			0x20




/*
 * 
 * Function prototypes / macros
 *
 */

//
// Removes all drawn overlay objects.
//
void overlay_clear(void);

//
// Releases all drawn overlay objects.
// Use this macro instead of overlay_clear() if all underlay blocks were restored or repalaced manually.
//
#ifdef OVERLAY_INVERSE_PRIORITY
#define overlay_release()                   ({ extern unsigned char overlay_block_id; extern unsigned char *s_addr[OVERLAY_BLOCK_COUNT]; memset(s_addr,0,sizeof(s_addr)); overlay_block_id=0; })
#else
#define overlay_release()                   ({ extern unsigned char overlay_block_id; overlay_block_id = 0; })

//
// Returns number of currently used  blocks.
//
#define overlay_get_used_block_count()      ({ extern unsigned char overlay_block_id; overlay_block_id; })
#endif


//
// Puts an overlay image at pointer img stored in flash with dimensions width, height to selected window at x, y.
// Returned value: 0 if OK, else if not.
// note: configuration - dependent function arguments are used to allow optimizer to always do best job,
//       even in high-level usage of this function.
//


#ifdef OVERLAY_DRAW_PARAM
#define overlay_draw( x, y, img, width, height) overlay_draw_param(x,y,img,width,height,0)  //overloading.
unsigned char overlay_draw_param
#else
unsigned char overlay_draw
#endif
(
#ifdef OVERLAY_DRAW_SAFE
	signed int x, signed int y, 
#else
	unsigned char x, unsigned char y,
#endif
	PGM_P img, 
	unsigned char width, unsigned char height
#ifdef OVERLAY_DRAW_PARAM
	, unsigned char param
#endif
);



//
// Primitives
//
unsigned char overlay_putpixel (unsigned char x, unsigned char y, unsigned char color);
unsigned char overlay_line     (unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, unsigned char color);
unsigned char overlay_bar      (unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, unsigned char color);
unsigned char overlay_circle   (unsigned char x, unsigned char y,  unsigned char r, unsigned char color);



/*
 *
 * Some high-level useful macros.
 *
 */

//
// draws an overlay sprite from tileset to window wnd.
//

#ifdef OVERLAY_WINDOW

#define overlay_draw_sprite( x, y, sprite )		\
	({overlay_draw( x, y,(uint8_t *)&(window_get_tileset())[(sprite) * DRIVER_BLOCK_SIZE], 8, DRIVER_BLOCK_HEIGHT);})
#define overlay_draw_sprite_wnd( x, y, sprite, wnd )		\
	({overlay_draw( x, y,(uint8_t *)&(awindow_get_tileset(wnd))[(sprite) * DRIVER_BLOCK_SIZE], 8, DRIVER_BLOCK_HEIGHT);})
#define overlay_draw_sprite_param( x, y, sprite, param )		\
	({overlay_draw_param( x, y,(uint8_t *)&(window_get_tileset())[(sprite) * DRIVER_BLOCK_SIZE], 8, DRIVER_BLOCK_HEIGHT, param);})
#define overlay_draw_sprite_wnd_param( x, y, sprite, param, wnd )		\
	({overlay_draw_param( x, y,(uint8_t *)&(awindow_get_tileset(wnd))[(sprite) * DRIVER_BLOCK_SIZE], 8, DRIVER_BLOCK_HEIGHT, param);})

#else

#define overlay_draw_sprite( x, y, sprite )		\
	({overlay_draw( x, y,(uint8_t *)&(driver_get_tileset())[(sprite) * DRIVER_BLOCK_SIZE], 8, DRIVER_BLOCK_HEIGHT);})
#define overlay_draw_sprite_param( x, y, sprite, param )		\
	({overlay_draw_param( x, y,(uint8_t *)&(driver_get_tileset())[(sprite) * DRIVER_BLOCK_SIZE], 8, DRIVER_BLOCK_HEIGHT, param);})

#endif

/*
 *
 * Compatibility.
 *
 */

#define putimage(x,y,img,width,height)      overlay_draw(x, y, img, width, height);
#define sprite_put(id,x,y,sprite)           overlay_draw_sprite(x, y, sprite)
#define sprite_init()
#define sprite_clear()                      overlay_clear()
#define SPRITE_COUNT                        (OVERLAY_BLOCK_COUNT/2)


#endif  //!_OVERLAY_H_
